package com.naiterui.ehp.bs.im.api;

import com.alibaba.fastjson.JSON;
import com.naiterui.ehp.bp.bo.im.MsgSendParamBO;
import com.naiterui.ehp.bp.bo.im.UserCommonParams;
import com.naiterui.ehp.bp.bo.im.UserSessionStatusBO;
import com.naiterui.ehp.bp.constants.ImConstants;
import com.naiterui.ehp.bp.constants.SwaggerTag;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.support.utils.IpUtil;
import com.naiterui.ehp.bs.im.dto.SendMessageDTO;
import com.naiterui.ehp.bs.im.exception.ExceptionCodes;
import com.naiterui.ehp.bs.im.exception.NaiteruiIMException;
import com.naiterui.ehp.bs.im.network.protocl.Message;
import com.naiterui.ehp.bs.im.service.IMessageService;
import com.naiterui.ehp.bs.im.service.INaiteruiIMService;
import com.naiterui.ehp.bs.im.service.ISessionService;
import com.naiterui.ehp.bs.im.utils.Constants;
import com.naiterui.ehp.bs.im.vo.*;
import com.naiterui.ehp.bs.im.vo.dto.MedicalRecordDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Api(tags = {SwaggerTag.BADACHU + SwaggerTag.IM})
@RestController
@AllArgsConstructor
public class ChatMessageApi {

    private static final Logger LOGGER = LoggerFactory.getLogger(ChatMessageApi.class);

    private final INaiteruiIMService naiteruiIMService;
    private final ISessionService sessionService;
    private final IMessageService messageService;

    @ApiOperation(value = "new获取与MQTT Broker建立连接的参数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "获取参数的用户id（医生、患者）", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "token", value = "医生、患者token", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "origin", value = "应用来源 0：患者App,1：医生App,2：患者微信,3：互联网医院(PC)", paramType = "querey", dataType = "int", required = true)
    })
    @RequestMapping(value = "/chatMessage/connect/params", method = RequestMethod.POST)
    public MqttConnectParam getMqttConnectionParams(Long userId, String token, Integer origin, HttpServletRequest request) throws Exception {
        LOGGER.info("获取与MQTT Broker建立连接的参数 userId: {}, token: {}, origin: {}", userId, token, origin);
        if (userId == null) {
            throw new NaiteruiIMException(ExceptionCodes.CONNECT_USER_ID_IS_NULL);
        }
        String ip = IpUtil.getIp(request);
        // 只有当发送的是文本消息并且消息的内容中包含药品名字时才会数组才不会为空
        MqttConnectParam connParam = this.naiteruiIMService.getMqttConnectionParams(origin, userId, token, ip);
        return connParam;
    }

    @ApiOperation(value = "new消息发送接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "message", value = "消息体json格式", paramType = "querey", dataType = "string", required = true),
            @ApiImplicitParam(name = "origin", value = "应用来源 0：患者App,1：医生App,2：患者微信,3：互联网医院(PC)", paramType = "querey", dataType = "int", required = true)
    })
    @PostMapping(value = "/chatMessage/chat/sendMessage")
    public ResponseVO<Object> sendMessage(String message, Integer origin) throws Exception {
        // 调用消息发送接口
        LOGGER.info("sendMessage:{},origin:{}.", message, origin);
        // 消息处理
        MessageVO result = this.naiteruiIMService.sendMessage(origin, message);
        if (result.getConsultPayStatus() != null) {
            Map<String, Object> consultCostMap = new HashMap<>();
            consultCostMap.put("doctorName", result.getDoctorName());
            consultCostMap.put("consultCost", result.getConsultPrice());
            if (result.getConsultPayStatus() == Constants.SESSION_PAY_STATUS_FAIL) {// 支付失败
                return PublicService.returnResponseVO(ExceptionCodes.SESSION_NEED_PAID, consultCostMap);
            }
            if (result.getConsultPayStatus() == Constants.SESSION_PAY_STATUS_PAYMENT_IN) {// 支付结果未确认
                return PublicService.returnResponseVO(ExceptionCodes.SESSION_BEING_PAID, consultCostMap);
            }
        }
        return PublicService.returnResponseVO(result);
    }


    @ApiOperation(value = "new文件上传接口 用于客户端发送多媒体文件 图片、音频、小视频")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "文件", paramType = "form", dataType = "__file", required = true),
            @ApiImplicitParam(name = "origin", value = "应用来源 0：患者App,1：医生App,2：患者微信,3：互联网医院(PC)", paramType = "querey", dataType = "int", required = true),
            @ApiImplicitParam(name = "platform", value = "平台 0：患者App,1：医生App,2：患者微信,3：互联网医院(PC)", paramType = "querey", dataType = "int", required = true)
    })
    @PostMapping(value = "/chatMessage/chat/media/upload")
    public ResponseVO<String> uploadMediaData(MediaUploadVO mediaUpload, @RequestParam(value = "file", required = false) MultipartFile[] file) throws Exception {
        // 调用消息发送接口
        Integer origin = this.getOrigin(mediaUpload.getOrigin());
        Integer platform = this.getPlatform(mediaUpload.getPlatform());
        mediaUpload.setOrigin(origin);
        mediaUpload.setPlatform(platform);
        // 上传文件
        String fileURL = this.naiteruiIMService.uploadMediaData(mediaUpload, file);
        return PublicService.returnResponseVO(fileURL);
    }

    @ApiOperation(value = "new会话详情信息")
    @ApiImplicitParam(name = "origin", value = "应用来源 0：患者App,1：医生App,2：患者微信,3：互联网医院(PC)", paramType = "querey", dataType = "int", required = true)
    @PostMapping(value = "/chatMessage/session/details")
    public PageVO<?> sessionDetails(String sessionId, Integer pageNo, Integer pageSize, Long endTime, Long doctorId, Long patientId,
                                    @RequestParam(value = "origin", required = true) Integer origin) throws Exception {
        LOGGER.info("session details, sessionId: {}, pageNo: {}, pageSize: {}, endTime: {}, doctorId: {}, patientId: {}",
                sessionId, pageNo, pageSize, endTime, doctorId, patientId);
        return this.naiteruiIMService.findMessagesBySession(sessionId, pageNo, pageSize, endTime, origin, doctorId, patientId);
    }

    @ApiOperation(value = "new患者支付完成后创建付费会话")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "patientId", value = "就诊人id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "patientName", value = "就诊人姓名", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "doctorId", value = "医生id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "doctorName", value = "医生姓名", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "payAmount", value = "患者支付金额", paramType = "querey", dataType = "Integer", required = false),
            @ApiImplicitParam(name = "orderSn", value = "互联网医院关联的订单号", paramType = "querey", dataType = "String", required = false),
            @ApiImplicitParam(name = "askSource", value = "1-普通付费咨询2-找医生", paramType = "querey", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "userId", value = "患者id", paramType = "querey", dataType = "long", required = false)
    })
    @PostMapping("/chatMessage/consult/session/init")
    public SessionVO paidConsult(ConsultInitVO consultInitVO) throws BusinessException {
        if (null == consultInitVO || consultInitVO.getPatientId() == null || consultInitVO.getDoctorId() == null
                || consultInitVO.getPayAmount() == null || StringUtils.isEmpty(consultInitVO.getDoctorName())
                || StringUtils.isEmpty(consultInitVO.getPatientName())) {
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        LOGGER.info("患者支付完成后创建付费会话,params:{}", consultInitVO.toString());
        return this.naiteruiIMService.createConsultSessionAndNoticeNew(consultInitVO);
    }


    @ApiOperation(value = "new内部服务结束会话")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "patientId", value = "患者id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "triggerSource", value = "1：医生手动结束会话  2：删除患者结束会话", paramType = "querey", dataType = "Integer", required = true)
    })
    @PostMapping("/chatMessage/inner/session/finish")
    public ResponseVO<String> finishSession(Long doctorId, Long patientId, Integer triggerSource) throws NaiteruiIMException {
        LOGGER.info("服务内部结束会话接口 参数,doctorId:{},patientId:{},triggerSource:{}", doctorId, patientId, triggerSource);
        // 验证字段
        if (doctorId == null || patientId == null || triggerSource == null) {
            throw new NaiteruiIMException(ExceptionCodes.PARAM_ERROR);
        }
        this.sessionService.finishSessionByDeletePatient(doctorId, patientId, triggerSource);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, "操作成功");
    }


    @ApiOperation(value = "new根据医生id,患者id查询当前是否有会话")
    @PostMapping("/chatMessage/inner/session/isalive")
    public ResponseVO<List<UserSessionStatusBO>> sessionStatus(UserCommonParams userCommonParams) throws NaiteruiIMException {
        LOGGER.info("请求参数:{}", userCommonParams.toString());
        if (userCommonParams.getDoctorIds() == null || userCommonParams.getDoctorIds().size() == 0 || userCommonParams.getPatientId() == null) {
            throw new NaiteruiIMException(ExceptionCodes.PARAM_ERROR);
        }
        List<UserSessionStatusBO> statusList = this.sessionService.isSessionAlive(userCommonParams.getDoctorIds(), userCommonParams.getPatientId());
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, statusList);
    }

    @ApiOperation(value = "发送系统消息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "patientId", value = "患者id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "doctorId", value = "医生id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "content", value = "消息内容", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "askType", value = "咨询类型 0：普通  1：专家", paramType = "querey", dataType = "int", required = true),
            @ApiImplicitParam(name = "patientOnlineOrderId", value = "订单号", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "doctorName", value = "医生名称", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "headUrl", value = "头像", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "patientName", value = "患者名称", paramType = "querey", dataType = "String", required = true)
    })
    @PostMapping("/chatMessage/inner/sys/message/send")
    public ResponseVO<Void> sendSysMessage(@RequestBody MsgSendParamBO msgSendParamBO) throws BusinessException {
        LOGGER.info("发送系统消息 : body={}", JSON.toJSONString(msgSendParamBO));
        if(msgSendParamBO.getDoctorId() == null || msgSendParamBO.getPatientId() == null || StringUtils.isEmpty(msgSendParamBO.getContent())){
            throw new NaiteruiIMException(ExceptionCodes.PARAM_ERROR);
        }
        msgSendParamBO.setVisualType(Message.MESSAGE_VISUAL_TYPE_ALL);          // 消息可见级别
        msgSendParamBO.setSysMsgType(Message.SYS_MSG_TYPE_CONSUMER);            // 消息类型
        msgSendParamBO.setMsgType(ImConstants.MESSAGE_TYPE_FIRST_BIND_UNNAMED); // 消息类型
        msgSendParamBO.setRelation(ImConstants.MESSAGE_RESOURCE_DOCTOR);        // 医生端
        this.naiteruiIMService.sendSysMessage(msgSendParamBO);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    @ApiOperation(value = "查看病情描述")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "patientId", value = "患者id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "patientName", value = "患者名称", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "doctorId", value = "医生id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "doctorName", value = "医生名称", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "age", value = "性别 0女1男2未知", paramType = "querey", dataType = "int", required = true),
            @ApiImplicitParam(name = "ageUnit", value = "年龄单位 岁，个月，周", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "idCard", value = "就诊卡号", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "descript", value = "病情描述", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "askType", value = "咨询类型  0：普通  1：专家", paramType = "querey", dataType = "int", required = true),
            @ApiImplicitParam(name = "patientOnlineOrderId", value = "订单号", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "doctorName", value = "医生名称", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "headUrl", value = "头像", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "patientName", value = "患者名称", paramType = "querey", dataType = "String", required = true)
    })
    @PostMapping("/chatMessage/inner/patientsMedicalRecord/send")
    public ResponseVO<Integer> sendPatientsMedicalRecord(@RequestBody MedicalRecordDTO medicalRecordDTO) throws Exception {
        LOGGER.info("发送病情描述 : body={}", JSON.toJSONString(medicalRecordDTO));
        // 判断参数是否传递
        if (medicalRecordDTO.getDoctorId() == null || medicalRecordDTO.getPatientId() == null || StringUtils.isEmpty(medicalRecordDTO.getDoctorName())
            || StringUtils.isEmpty(medicalRecordDTO.getPatientName()) || medicalRecordDTO.getAge() == null || StringUtils.isEmpty(medicalRecordDTO.getAgeUnit())
            || StringUtils.isEmpty(medicalRecordDTO.getDescript()) || StringUtils.isEmpty(medicalRecordDTO.getIdCard())) {
            throw new NaiteruiIMException(ExceptionCodes.PARAM_ERROR);
        }
        // 睡眠1秒
        Thread.sleep(0 * 1000L);
        Integer sendResult = this.messageService.sendPatientsMedicalRecord(medicalRecordDTO, null);
        return PublicService.returnResponseVO(sendResult);
    }

    // 根据消息类型发送消息
    @ApiOperation(value = "根据消息类型发送消息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "patientId", value = "患者id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "doctorId", value = "医生id", paramType = "querey", dataType = "long", required = true),
            @ApiImplicitParam(name = "origin", value = "应用来源 0：患者App,1：医生App,2：患者微信,3：互联网医院(PC)", paramType = "querey", dataType = "int", required = true),
            @ApiImplicitParam(name = "msgType", value = "发送消息类型 10017：医生发送文章  10016：加号  10018：医生已接诊  10008：咨询已结束", paramType = "querey", dataType = "int", required = true),
            @ApiImplicitParam(name = "content", value = "消息内容", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "askType", value = "咨询类型 0：普通 1：专家", paramType = "querey", dataType = "int", required = true),
            @ApiImplicitParam(name = "patientOnlineOrderId", value = "订单号", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "doctorName", value = "医生名称", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "headUrl", value = "头像", paramType = "querey", dataType = "String", required = true),
            @ApiImplicitParam(name = "patientName", value = "患者名称", paramType = "querey", dataType = "String", required = true)
    })
    @PostMapping("/chatMessage/inner/sendMessageByType")
    public ResponseVO<Integer> sendMessageByType(@RequestBody SendMessageDTO sendMessageDTO) throws Exception {
        LOGGER.info("根据消息类型发送消息 : body={}", JSON.toJSONString(sendMessageDTO));
        // 判断参数是否传递
        if (sendMessageDTO.getPatientId() == null || sendMessageDTO.getDoctorId() == null || sendMessageDTO.getOrigin() == null || sendMessageDTO.getMsgType() == null
                || StringUtils.isEmpty(sendMessageDTO.getContent())) {
            throw new NaiteruiIMException(ExceptionCodes.PARAM_ERROR);
        }
        Integer sendResult = this.messageService.sendMessageByType(sendMessageDTO);
        return PublicService.returnResponseVO(sendResult);
    }

    private int getOrigin(Integer origin) throws NaiteruiIMException {
        // 校验参数合法性
        return this.naiteruiIMService.checkOrigin(origin == null ? null : origin.toString());
    }

    private int getPlatform(Integer platform) throws NaiteruiIMException {
        // 校验参数合法性
        return this.naiteruiIMService.checkPlatform(platform == null ? null : platform.toString());
    }
}
